package com.yx.myinterest;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;


import com.yx.myinterest.log.LogUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

/**
 * Creator:Yx
 * Time:2023/3/6 13:46
 * Description: 点赞，上漂浮动画
 */
public class LikeView extends View implements Runnable {

    // 持续时间 0.010F ~ 0.2F
    public static final float mDuration = 0.015F;
    // 偏移发散图形在View中的默认出现高度
    public static final int mDefaultHeight = 100;
    // 点击间隔时间
    protected static final long mQueenDuration = 200;

    protected final Random mRandom = new Random();
    private int mIndex = 0;
    // 偏移发散图标集合 - 执行完毕会清除直到为0
    protected ArrayList<DivergeInfo> mDivergeInfos;
    // 偏移发散图标下标- 快速点击会累加[0 1 2 3 4 0 1 2 3 4 0 1...] - 执行完毕会清除直到为0
    protected List<Object> mQueen;

    // 起始X Y 位置
    protected PointF mPtStart;
    // 结束X Y 位置
    protected PointF mPtEnd;

    // 死池
    protected ArrayList<DivergeInfo> mDeadPool = new ArrayList<>();

    // 图片绘制画笔
    private Paint mPaint;

    //    private static final int mDefaultWidth = 100;
    //    private static final int mAlphaOffset = 50;
    private ArrayList<Bitmap> mList;

    // 双击。上一次点击时间
    private long mLastAddTime = 0;

    private Thread mThread;

    // 是否执行循环动画 true循环执行，false 不执行
    private boolean mRunning = true;
    // 动画绘制状态，true绘制中，false onDraw绘制完毕
    private boolean mIsDrawing = false;

    public LikeView(Context context) {
        super(context);
        initView();
    }

    public LikeView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    private void initView() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        // 此处有点耗内存
        mList = new ArrayList<>();
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.icon_praise_sm1, null)).getBitmap());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.icon_praise_sm2, null)).getBitmap());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.icon_praise_sm3, null)).getBitmap());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.icon_praise_sm4, null)).getBitmap());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.icon_praise_sm5, null)).getBitmap());
        mList.add(((BitmapDrawable) ResourcesCompat.getDrawable(getResources(), R.drawable.icon_left_zan_red, null)).getBitmap());
    }

    public void startDiverges() {
        // 计数
        if (mIndex == mList.size()) {
            mIndex = 0;
        }

        // 偏移发散图形集合初始化
        if (mDivergeInfos == null) {
            // Add时初始容量为10，不初始容量和初始化了合适的容量，处理时间肯定不同，因初始化和扩容是需要时间的。故初始30容量
            mDivergeInfos = new ArrayList<>(30);
        }

        if (mQueen == null) { // 任何进行加锁的代码块，都是为了保护数据的一致性
            mQueen = Collections.synchronizedList(new ArrayList<>(30));
        }
        LogUtil.iYx("----设置发散图像下标为：" + mIndex);
        mQueen.add(mIndex);

        if (mThread == null) {
            mThread = new Thread(this);
            mThread.start();
        }

        mIndex++;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        LogUtil.iYx("----onDraw----" + mDivergeInfos);
        if (mRunning && mList != null && mDivergeInfos != null) {
            for (DivergeInfo divergeInfo : mDivergeInfos) {
                mPaint.setAlpha((int) (255 * divergeInfo.mY / mPtStart.y));
                canvas.drawBitmap(mList.get((Integer) divergeInfo.mType),
                        divergeInfo.mX,
                        divergeInfo.mY,
                        mPaint);
            }
        }
        mIsDrawing = false;
    }


    @Override
    public void run() {
        LogUtil.iYx("----开始Run了-----");
        while (mRunning) {
            if (mList == null) {
                continue;
            }
            if (mQueen == null) {
                continue;
            }
            if (mIsDrawing) {
                //如果正在绘制，不要处理数据
                continue;
            }
            if (mDivergeInfos == null) {
                continue;
            }

            // 执行间隔200MS
            dealQueen();
            if (mDivergeInfos.size() == 0) {
                continue;
            }
            dealDiverge();
            mIsDrawing = true;
            postInvalidate(); // 执行onDraw()
        }
        //停止
        release();
    }

    /**
     * 每点击一次，创建一个图形实体DivergeInfo
     */
    private void dealQueen() {
        long now = System.currentTimeMillis();
        if (mQueen.size() > 0 && now - mLastAddTime > mQueenDuration) {
            mLastAddTime = System.currentTimeMillis();
            DivergeInfo divergeInfo = null;
            if (mDeadPool != null && mDeadPool.size() > 0) {
                // 死池里面有空闲的divergeNode
                divergeInfo = mDeadPool.get(0);
                mDeadPool.remove(0);
            }
            if (divergeInfo == null) {
                divergeInfo = createDivergeNode(mQueen.get(0));
            }
            divergeInfo.reset();
            divergeInfo.mType = mQueen.get(0);
            mDivergeInfos.add(divergeInfo);
            mQueen.remove(0);
            LogUtil.iYx("---创建了1个Diverge图像，mQueen 还将创建(个)：" + mQueen.size());
        }
    }

    /**
     * 创建一个图形实体节点
     */
    protected DivergeInfo createDivergeNode(Object type) {
        if (mPtEnd == null) {
            LogUtil.iYx("----宽度----" + getMeasuredWidth());
            mPtEnd = new PointF(getMeasuredWidth() / 2, 0);
        }
        PointF endPoint = mPtEnd;
        if (endPoint == null) {
            endPoint = new PointF(mRandom.nextInt(getMeasuredWidth()), 0);
        }
        // int height = mDivergeViewProvider == null ? mDefaultHeight : mDivergeViewProvider.getBitmap(type).getHeight();
        if (mPtStart == null) {
            mPtStart = new PointF(getMeasuredWidth() / 2, getMeasuredHeight() - mDefaultHeight); // 默认起始高度
        }
        return new DivergeInfo(
                mPtStart.x,
                mPtStart.y,
                getBreakPointF(2, 3),
                endPoint,
                type);
    }

    // 贝塞尔曲线点
    private PointF getBreakPointF(int scale1, int scale2) {
        PointF pointF = new PointF();
        pointF.x = mRandom.nextInt((getMeasuredWidth() - getPaddingRight() + getPaddingLeft()) / scale1) + getMeasuredWidth() / scale2;
        pointF.y = mRandom.nextInt((getMeasuredHeight() - getPaddingBottom() + getPaddingTop()) / scale1) + getMeasuredHeight() / scale2;
        return pointF;
    }

    /**
     * 执行动画
     */
    private void dealDiverge() {
        for (int i = 0; i < mDivergeInfos.size(); i++) {
            DivergeInfo divergeInfo = mDivergeInfos.get(i);
            float timeLeft = 1.0F - divergeInfo.mDuration;
            divergeInfo.mDuration += mDuration;

            float x, y;

            // 二次贝塞尔
            float time1 = timeLeft * timeLeft;
            float time2 = 2 * timeLeft * divergeInfo.mDuration;
            float time3 = divergeInfo.mDuration * divergeInfo.mDuration;
            x = time1 * (mPtStart.x)
                    + time2 * (divergeInfo.mBreakPoint.x)
                    + time3 * (divergeInfo.mEndPoint.x);

            divergeInfo.mX = x;

            y = time1 * (mPtStart.y)
                    + time2 * (divergeInfo.mBreakPoint.y)
                    + time3 * (divergeInfo.mEndPoint.y);

            divergeInfo.mY = y;

            if (divergeInfo.mY <= divergeInfo.mEndPoint.y) {
                mDivergeInfos.remove(i);
                LogUtil.iYx("---图像移动完毕，删除：" + i + "  剩余：" + mDivergeInfos.size());
                mDeadPool.add(divergeInfo); // 删除的内容加入池中，等待下次重复使用
                i--;
                continue;
            }
        }
    }

    public void release() {
        LogUtil.iYx("----Release了-----");
        stop();
        mPtEnd = null;
        mPtStart = null;
        mDivergeInfos = null;
        mQueen = null;
        mDeadPool = null;
    }

    public void stop() {
        if (mDivergeInfos != null) {
            mDivergeInfos.clear();
        }
        if (mQueen != null) {
            mQueen.clear();
        }
        if (mDeadPool != null) {
            mDeadPool.clear();
        }
    }

    private static class DivergeInfo {
        public float mDuration;
        public PointF mBreakPoint;
        public PointF mEndPoint;
        public float mX;
        public float mY;
        public Object mType; // 用于指定展示哪个偏移图标
        public float mStartX;
        public float mStartY;

        public DivergeInfo(float x, float y, PointF breakPoint, PointF endPoint, Object type) {
            mDuration = 0.0f;
            mEndPoint = endPoint;
            mX = x;
            mY = y;
            mStartX = x;
            mStartY = y;
            mBreakPoint = breakPoint;
            mType = type;
        }

        public void reset() {
            mDuration = 0.0f;
            mX = mStartX;
            mY = mStartY;
        }
    }


}
